using System;
using System.Collections.Generic;
using System.Text;

using System.Data;
using System.Data.SqlClient;

using Sys.DataAccess;

namespace Pervote.Core.Logic
{
    public class PollManager
    {
        public enum VotingErrors
        {
            SystemError = -1,
            OK = 0,
            AlreadyVoted = 1,
            UserNameIsNull = 2,
            MissingParameters = 3
        }

        public enum Errors
        {
            OK = 0,
            MissingParameters = 3
        }

        private static DatabaseCommand.CreateCommand commandCreator = DatabaseCommand.GetCreateCommand(PervoteSettings.ConnectionString, DatabaseType.SqlServer);

        public long CreatePoll(Poll poll, ErrorInfo error)
        {
            if (String.IsNullOrEmpty(poll.Title))
            {
                error.ErrorCode = (int)Errors.MissingParameters;
                error.Message = "Poll title is empty.";
                return 0;
            }
            DatabaseCommand command = commandCreator("PV_SP_CreatePoll", CommandType.StoredProcedure, false);
            command.AddInParameter("Title", poll.Title);
            command.AddInParameter("CategoryId", poll.CategoryId);
            command.AddInParameter("StartedBy", poll.StartedBy);
            command.AddInParameter("Description", poll.Description);
            command.AddInParameter("AllowPics", poll.AllowPics);
            command.AddInParameter("AllowAudio", poll.AllowAudio);
            command.AddInParameter("AllowVideo", poll.AllowVideo);
            command.AddInParameter("ItemsLocked", poll.ItemsLocked);
            command.AddInParameter("AllowMultipleVotes", poll.AllowMultipleVotes);
            command.AddOutputParameter("PollId", DbType.Int64);
            error.ErrorCode = (int)command.ExecuteScalar();
            long pollId = (long)command.GetParameterValue("PollId");
            return pollId;
        }

        public long AddItem(PollItem item, ErrorInfo error)
        {
            if (String.IsNullOrEmpty(item.Name))
            {
                error.ErrorCode = (int)Errors.MissingParameters;
                error.Message = "The item is empty.";
                return 0;
            }
            DatabaseCommand command = commandCreator("PV_SP_AddItem", CommandType.StoredProcedure, false);
            command.AddInParameter("PollId", item.PollId);
            command.AddInParameter("Name", item.Name);
            command.AddInParameter("AddedBy", item.AddedBy);
            command.AddOutputParameter("ItemId", DbType.Int64);
            error.ErrorCode = (int)command.ExecuteScalar();
            long itemId = (long)command.GetParameterValue("ItemId");
            return itemId;
        }

        public long AddItemComment(long itemId, PollItemComment comment, ErrorInfo error)
        {
            //Remove un-necessary white spaces.
            if (!string.IsNullOrEmpty(comment.Text)) comment.Text = comment.Text.Trim();
            if (!string.IsNullOrEmpty(comment.Link)) comment.Link = comment.Link.Trim();
            
            //if both are null/empty, RETURN
            if (string.IsNullOrEmpty(comment.Text) && string.IsNullOrEmpty(comment.Link))
            {
                error.ErrorCode = (int)Errors.MissingParameters;
                error.Message = "The comment is empty.";
                return 0;
            }

            //if comment is empty, and link exists, give an informative message
            if (string.IsNullOrEmpty(comment.Text))
            {
                comment.Text = "Read more at external website.";
            }

            //Add http:// to link, if the user forgot to add it.
            if (!string.IsNullOrEmpty(comment.Link))
            {
                comment.Link = comment.Link.Trim();
                if (!comment.Link.ToLower().StartsWith("http://")) comment.Link = "http://" + comment.Link;
            }

            DatabaseCommand command = commandCreator("PV_SP_AddComment", CommandType.StoredProcedure, false);
            command.AddInParameter("ItemId", itemId);
            command.AddInParameter("Text", comment.Text);
            command.AddInParameter("Link", comment.Link);
            command.AddInParameter("AddedBy", comment.AddedBy);
            command.AddOutputParameter("CommentId", DbType.Int64);
            error.ErrorCode = (int)command.ExecuteScalar();
            long commentId = (long)command.GetParameterValue("CommentId");
            return commentId;
        }

        public List<Poll> GetRandomPolls(string fqCategoryName, int numPolls, ErrorInfo errors)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetRandomPollsShortView", CommandType.StoredProcedure, false);
            command.AddInParameter("FQCategoryName", fqCategoryName);
            command.AddInParameter("NumPolls", numPolls);
            return command.GetList<Poll>();
        }

        public List<Poll> SearchPolls(string searchKeyword, ErrorInfo errors)
        {
            DatabaseCommand command = commandCreator("PV_SP_SearchPolls", CommandType.StoredProcedure, false);
            command.AddInParameter("SearchKey", searchKeyword);
            return command.GetList<Poll>();
        }

        public PollItem GetPollItem(long itemId, ErrorInfo errors)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetPollItem", CommandType.StoredProcedure, false);
            command.AddInParameter("ItemId", itemId);
            return command.GetObject<PollItem>();
        }

        public Poll GetPollView(long pollId, string userName, ErrorInfo errors)
        {
            Poll poll = new Poll(); //The only result.
            DatabaseCommand command = commandCreator("PV_SP_GetPollView", CommandType.StoredProcedure, false);
            command.AddInParameter("Id", pollId);
            command.AddInParameter("UserName", userName);
            poll = command.GetObject<Poll>();
            if (poll == null) return null;

            //Get the Poll Items
            command = commandCreator("PV_SP_GetPollItems", CommandType.StoredProcedure, false);
            command.AddInParameter("PollId", pollId);
            command.AddInParameter("UserName", userName);
            command.AddInParameter("StartRank", 1);
            command.AddInParameter("NumItems", PervoteSettings.ShortPollViewItemCount);
            poll.PollItems = command.GetList<PollItem>();
            return poll;
        }

        public void Vote(long itemId, string userName, ref long totalVotes, ref bool canVoteAgain, ErrorInfo errors)
        {
            if (String.IsNullOrEmpty(userName))
            {
                errors.ErrorCode = (int)VotingErrors.UserNameIsNull;
                return;
            }
            DatabaseCommand command = commandCreator("PV_SP_AddVote", CommandType.StoredProcedure, false);
            command.AddInParameter("ItemId", itemId);
            command.AddInParameter("UserName", userName);
            command.AddOutputParameter("TotalVotes", DbType.Int64);
            command.AddOutputParameter("CanVoteAgain", DbType.Boolean);
            errors.ErrorCode = (int)command.ExecuteScalar();
            totalVotes = (long)command.GetParameterValue("TotalVotes");
            canVoteAgain = (bool)command.GetParameterValue("CanVoteAgain");
        }

        public List<PollItemComment> GetItemComments(long itemId, string userName, int startRank, int num, ErrorInfo errors)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetItemComments", CommandType.StoredProcedure, false);
            command.AddInParameter("ItemId", itemId);
            command.AddInParameter("UserName", userName);
            command.AddInParameter("StartRank", startRank);
            command.AddInParameter("NumComments", num);
            return command.GetList<PollItemComment>();
        }

        public long LogPollIssue(long pollId, string issueType, string description, string userName, ErrorInfo errors)
        {
            DatabaseCommand command = commandCreator("PV_SP_LogPollIssue", CommandType.StoredProcedure, false);
            command.AddInParameter("PollId", pollId);
            command.AddInParameter("IssueType", issueType);
            command.AddInParameter("Description", description);
            command.AddInParameter("ReportedBy", userName);
            command.AddOutputParameter("LogId", DbType.Int64);
            command.ExecuteNonQuery();
            long logId = (long)command.GetParameterValue("LogId");
            return logId;
        }

        public List<Poll> GetPolls(string fqCatName, int startRank, int numPolls)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetPolls", CommandType.StoredProcedure, false);
            command.AddInParameter("FQCategoryName", fqCatName);
            command.AddInParameter("StartRank", startRank);
            command.AddInParameter("NumPolls", numPolls);
            return command.GetList<Poll>();
        }

        public List<Poll> GetHotPollsList(string fqCatName, int startRank, int numPolls, int periodInHours)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetHotPollsListView", CommandType.StoredProcedure, false);
            command.AddInParameter("FQCategoryName", fqCatName);
            command.AddInParameter("StartRank", startRank);
            command.AddInParameter("NumPolls", numPolls);
            command.AddInParameter("PeriodInHours", periodInHours);
            return command.GetList<Poll>();
        }

        public List<Poll> GetTopPollsList(string fqCatName, int startRank, int numPolls)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetTopPollsListView", CommandType.StoredProcedure, false);
            command.AddInParameter("FQCategoryName", fqCatName);
            command.AddInParameter("StartRank", startRank);
            command.AddInParameter("NumPolls", numPolls);
            return command.GetList<Poll>();
        }

        public List<Poll> GetNewPollsList(string fqCatName, int startRank, int numPolls)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetNewPollsListView", CommandType.StoredProcedure, false);
            command.AddInParameter("FQCategoryName", fqCatName);
            command.AddInParameter("StartRank", startRank);
            command.AddInParameter("NumPolls", numPolls);
            return command.GetList<Poll>();
        }

        public List<Poll> GetRandomPollsList(string fqCatName, int numPolls)
        {
            DatabaseCommand command = commandCreator("PV_SP_GetRandomPollsListView", CommandType.StoredProcedure, false);
            command.AddInParameter("FQCategoryName", fqCatName);
            command.AddInParameter("NumPolls", numPolls);
            return command.GetList<Poll>();
        }

        public void RateComment(long commentId, int rating, string userName, ErrorInfo error)
        {
            DatabaseCommand command = commandCreator("PV_SP_RateComment", CommandType.StoredProcedure, false);
            command.AddInParameter("CommentId", commentId);
            command.AddInParameter("RatedBy", userName);
            command.AddInParameter("Positive", (rating == 1) ? true : false);
            error.ErrorCode = (int)command.ExecuteScalar();
        }
    }
}
